package com.bootdo.system.controller;

import com.bootdo.common.annotation.Log;
import com.bootdo.common.controller.BaseController;
import com.bootdo.common.domain.FileDO;
import com.bootdo.common.domain.Tree;
import com.bootdo.common.service.FileService;
import com.bootdo.common.utils.MD5Utils;
import com.bootdo.common.utils.R;
import com.bootdo.common.utils.ShiroUtils;
import com.bootdo.system.dao.UserDao;
import com.bootdo.system.domain.MenuDO;
import com.bootdo.system.domain.UserDO;
import com.bootdo.system.service.MenuService;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.support.incrementer.SybaseAnywhereMaxValueIncrementer;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
public class LoginController extends BaseController {
    private static String USER;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final MenuService menuService;
    private final FileService fileService;
    private final DefaultKaptcha defaultKaptcha;
    private final UserDao userDao;
    @Autowired
    public LoginController(MenuService menuService, FileService fileService, DefaultKaptcha defaultKaptcha, UserDao userDao) {
        this.menuService = menuService;
        this.fileService = fileService;
        this.defaultKaptcha = defaultKaptcha;
        this.userDao = userDao;
    }

    public static String getUSER() {
        return USER;
    }

    private static void setUSER(String USER) {
        LoginController.USER = USER;
    }

    @GetMapping({"/", ""})
    String welcome(Model model) {
        return "redirect:/login";
    }

    @Log("请求访问主页")
    @GetMapping({"/index"})
    String index(Model model) {
        List<Tree<MenuDO>> menus = menuService.listMenuTree(getUserId());
        model.addAttribute("menus", menus);
        model.addAttribute("name", getUser().getName());
        FileDO fileDO = fileService.get(getUser().getPicId());
        if (fileDO != null && fileDO.getUrl() != null) {
            if (fileService.isExist(fileDO.getUrl())) {
                model.addAttribute("picUrl", fileDO.getUrl());
            } else {
                model.addAttribute("picUrl", "/img/photo_s.png");
            }
        } else {
            model.addAttribute("picUrl", "/img/photo_s.png");
        }
        model.addAttribute("username", getUser().getUsername());
        return "index_v1";
    }

    @GetMapping("/login")
    String login() {
        return "login";
    }

    @Log("登录")
    @PostMapping("/login")
    @ResponseBody
    R ajaxLogin(String username, String password) {
        password = MD5Utils.encrypt(username, password);
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            setUSER(username);
            loginError.remove(username);
            return R.ok();
        } catch (AuthenticationException e) {
            if (loginError.containsKey(username)){
                Map<String,Long> map = loginError.get(username);
                Long firstErrorTime = map.get("firstErrorTime");
                if ((System.currentTimeMillis() - firstErrorTime) < 300000){
                    if ((map.get("frequency") + 1) >= 3){ // 错误三次直接锁定
                        userDao.setStatusByUsername(username,0);
                    }else {
                        map.put("frequency",map.get("frequency")+1);
                    }
                }else {//超过5分钟后清空
                    loginError.remove(username);
                    Map<String,Long> m = new HashMap<>();
                    m.put("firstErrorTime",System.currentTimeMillis());
                    m.put("frequency",1L);
                    loginError.put(username,m);
                }
            }else {
                Map<String,Long> map = new HashMap<>();
                map.put("firstErrorTime",System.currentTimeMillis());
                map.put("frequency",1L);
                loginError.put(username,map);
            }
            return R.error(e.getMessage());
        }
    }

    private Map<String,Map<String,Long>> loginError = new HashMap<>();

    @GetMapping("/defaultKaptcha")
    public void defaultKaptcha(HttpSession session, HttpServletResponse httpServletResponse) throws Exception {
        byte[] captchaChallengeAsJpeg = null;
        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
        try {
            //生产验证码字符串并保存到session中
            String createText = defaultKaptcha.createText();
            session.setAttribute("verifyCode", createText);
            //使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中
            BufferedImage challenge = defaultKaptcha.createImage(createText);
            ImageIO.write(challenge, "jpg", jpegOutputStream);
        } catch (IllegalArgumentException e) {
            httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        //定义response输出类型为image/jpeg类型，使用response输出流输出图片的byte数组
        captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
        httpServletResponse.setHeader("Cache-Control", "no-store");
        httpServletResponse.setHeader("Pragma", "no-cache");
        httpServletResponse.setDateHeader("Expires", 0);
        httpServletResponse.setContentType("image/jpeg");
        ServletOutputStream responseOutputStream =
                httpServletResponse.getOutputStream();
        responseOutputStream.write(captchaChallengeAsJpeg);
        responseOutputStream.flush();
        responseOutputStream.close();
    }

    @ResponseBody
    @RequestMapping(value = "/verifyDefaultKaptcha/{verifyCode}", method = RequestMethod.GET)
    public String verifyControllerDefaultKaptcha(@PathVariable String verifyCode, HttpSession session) {
//        String captchaId = (String) session.getAttribute("verifyCode");
//        if (captchaId == null) {
//            captchaId = "";
//        }
//        System.out.println("Session  verifyCode " + captchaId + " form verifyCode " + verifyCode);
//        if (!captchaId.equals(verifyCode)) {
//            return "false";
//        } else {
//            return "true";
//        }
        return "true";
    }

    @GetMapping("/logout")
    String logout() {
        ShiroUtils.logout();
        setUSER("");
        return "redirect:/login";
    }

    @GetMapping("/main")
    String main() {
        return "main";
    }

}
